//
//  CZRefreshControl.swift
//  新浪微博
//
//  Created by 名品导购网MPLife.com on 2017/12/7.
//  Copyright © 2017年 sweet. All rights reserved.
//

import UIKit
//刷新状态临界点
private let CZRefreshOffset:CGFloat = 126
/// 刷新状态
///
/// - Normal: 普通状态
/// - Pulling: 超过临界点 如果放手 开始刷新
/// - WillRefresh: 用户超过临界点 并且放手
enum CZRefreshState{
    case Normal
    case Pulling
    case WillRefresh
}
//刷新控件 专门负责刷新相关的逻辑处理
class CZRefreshControl: UIControl {
    //属性
    //滚动视图的父视图  下拉刷新控件应该适用于tablevIEW/collectionView
    private weak var scrollerView:UIScrollView?
//    private lazy var refreshView:CZRefreshView = CZRefreshView()
    private lazy var refreshView:CZMeiTuanRefreshView = CZMeiTuanRefreshView()
    //构造函数
    init() {
        super.init(frame: CGRect())
        setupUI()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupUI()
//        fatalError("init(coder:) has not been implemented")
    }
    //newSuperview  addSubView方法会调用
    //当添加到父视图的父视图的时候 ，newsuperView是父视图
    //当父视图被移除 newSuperview 是nil
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        guard let sv = newSuperview as? UIScrollView else {
            return
        }
        //记录父视图
        scrollerView = sv
        //KVO监听父视图的contentoffset
        //KVO要监听的对象负责添加监听者
        scrollerView?.addObserver(self, forKeyPath: "contentOffset", options: [], context: nil)
    }
    //importantPoint 回顾下拉刷新知识点
    /*
     所有的下拉刷新框架都是监听父视图的contentoffset
     用KVO监听，在removeFromSuper的时候移除监听 否则会导致程序奔溃，然后在监听到的事件中，实现下拉刷新的逻辑处理
 */
    //本视图从父视图上移除
    //所有的下拉刷新框架都是监听父视图的contentoffset 所有的框架KVO监听实现思路都是这个
    override func removeFromSuperview() {
        //superView还存在
        superview?.removeObserver(self, forKeyPath: "contentOffset")
        super.removeFromSuperview()
        //superView不存在
    }
    
    //所有KVO方法会统一调用此方法
    //观察者模式在不需要的时候都需要释放
    //通知中心 如果不释放什么都不发生 但会有内存泄露 会有多次注册的可能
    //KVO 如果不释放 会导致程序奔溃
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        //contentoffset 跟 contentInset 的 top有关
//        print(scrollerView?.contentOffset)
        //初始高度就应该是0
        guard let sv = scrollerView else {
            return
        }
        let height = -(sv.contentInset.top + sv.contentOffset.y)
        self.frame = CGRect(x: 0, y: -height, width: sv.bounds.width, height: height)
        //传递父视图高度 如果刷新 不传递
        //代码放在最合适的位置
        if refreshView.refreshState != .WillRefresh {
            refreshView.parentViewHeight = height
        }
        if height < 0 {
            return
        }else{
            let tempView:CZMeiTuanRefreshView = viewWithTag(900) as! CZMeiTuanRefreshView
            tempView.frame = CGRect(x: 0, y: -300+height, width: self.frame.size.width, height:300 )
        }
        //判断临界点
        if sv.isDragging {
            //拖拽
            if height > CZRefreshOffset && (refreshView.refreshState) == .Normal {
                print("放手刷新")
                refreshView.refreshState = .Pulling
            } else if height <= CZRefreshOffset && (refreshView.refreshState == .Pulling) {
                print("继续使劲...")
                refreshView.refreshState = .Normal
            }else{
                
            }
        }else{
            //放手 判断是否超过零界点
            if refreshView.refreshState == .Pulling{
            print("准备开始刷新")
                //刷新结束之后，将状态改为.Normal才能继续响应刷新
            /*refreshView.refreshState = .WillRefresh
                //让整个刷新视图能够显示出来
                //解决方法  修改表格的contentInset
                var inset = sv.contentInset
                inset.top += CZRefreshOffset
                sv.contentInset = inset*/
                beginRefreshing()
                //发送刷新数据的事件
                sendActions(for: .valueChanged)
        }
      }
    }
    //开始刷新
    func beginRefreshing() {
        //判断父视图
        guard let sv = scrollerView else {
            return
        }
        //判断是否正在刷新 直接返回
        if refreshView.refreshState == .WillRefresh {
           return
        }
        
        //设置刷新视图状态
        refreshView.refreshState = .WillRefresh
        //调整表格的间距
        var inset = sv.contentInset
        inset.top += CZRefreshOffset
        sv.contentInset = inset
        //设置刷新视图的父视图高度
        refreshView.parentViewHeight = CZRefreshOffset
    }
    //结束刷新
    func endRefreshing() {
        //恢复刷新视图的状态
        //恢复表格的contentInset
        guard let sv = scrollerView else {
            return
        }
        //判断状态 是否正在刷新 如果不是，直接返回
        if refreshView.refreshState != .WillRefresh {
            return
        }
        
        var inset = sv.contentInset
        inset.top -= CZRefreshOffset
        sv.contentInset = inset
        refreshView.refreshState = .Normal
    }
}

extension CZRefreshControl{
    private func setupUI(){
        refreshView.tag = 900
        refreshView.clipsToBounds = true
        refreshView.frame = CGRect(x: 0, y: -300, width: UIScreen.main.bounds.size.width, height: 300)
        addSubview(refreshView)
    }
}
























